library(ggplot2)
library(reshape2)
library(doBy)
loadData <- function(FILE,desc,label1,label2)
{
d <- read.csv(FILE,header = FALSE)
if(label2 > label1)
{
  tmp <- label2
  label2 <- label1
  label1 <- tmp
  tmp <- d[1]
  d[1] <- d[2]
  d[2] <- tmp
}
d$TimeStamp <- 1:nrow(d)
names(d) <- c(paste("Tenant 1 @",label1,"MB/s"), paste("Tenant 2 @",label2,"MB/s"),"Timestamp")
d <- melt(d,id.vars=c("Timestamp"))
names(d) <- c("Timestamp","Tenant","BW")
d$desc <- desc
d$label1 <- label1
d$label2 <- label2
return (d)
}
loadData1 <- function(FILE,desc,label1)
{
d <- read.csv(FILE,header = FALSE)
d$TimeStamp <- 1:nrow(d)
names(d) <- c("Tenant 1", "Timestamp")
d <- melt(d,id.vars=c("Timestamp"))
names(d) <- c("Timestamp","Tenant","BW")
d$desc <- desc
return (d)
}
draw1 <- function(dades)
{
  ggplot(dades)+geom_line(aes(x=Timestamp,y=BW,colour=Tenant,linetype=Tenant))+theme_bw(base_size = 14)+labs(title=(dades$desc))+theme( legend.position = "top")
}
drawsmooth <- function(dades)
{
  ggplot(dades)+geom_smooth(aes(x=Timestamp,y=BW,colour=Tenant,linetype=Tenant), degree=0, 
        span=0.05, se=FALSE)+theme_bw(base_size = 14)+labs(title=(dades$desc))+theme( legend.position = "top")
}
draw2 <- function(dades)
{
  ggplot(dades)+geom_boxplot(aes(x=Tenant,y=BW))+theme_bw()+labs(title=(dades$desc))
}
draw3 <- function(dades)
{
  ggplot(dades)+geom_violin(aes(x=Tenant,y=BW),draw_quantiles = c(0.5))+theme_bw()+labs(title=(dades$desc))
}
draw4 <- function(dades)
{
  ggplot(dades,aes(colour=Tenant,x=BW,linetype=Tenant))+ stat_ecdf(geom = "step")+geom_vline(xintercept=dades$label1,colour="black")+geom_vline(xintercept=dades$label2,colour="black")+theme_bw(base_size = 14)+labs(title=(dades$desc))+scale_y_continuous("ecdf")+theme(legend.position = "top")
}
 

Selected LOG1.CSV URV 100 / 20

Shows how the mechanism guarantee the 20 MB/s but does not guarantee the 100 MB/s ## Line plot + Violin plot

URV10020 <- loadData("../log1/log1.csv","URV 100 / 20", 100, 20)
draw1(URV10020)

drawsmooth(URV10020)+scale_y_continuous(limits=c(0,250))
Ignoring unknown parameters: degree
pdf(file="URV100_20_Timeline.pdf",width = 7, height= 5)
drawsmooth(URV10020)+scale_y_continuous(limits=c(0,250))
Ignoring unknown parameters: degree
dev.off()
png 
  2 

draw2(URV10020)

draw3(URV10020)

draw4(URV10020)+scale_x_continuous(limits=c(0,250))
pdf(file="URV100_20_ECDF.pdf",width = 7, height= 5)
draw4(URV10020)+scale_x_continuous(limits=c(0,250))
dev.off()
png 
  2 

summaryBy(.~Tenant,URV10020,id = ~Timestamp,FUN = c(quantile))

BSC filter allows to request a 100 / 20 BW and the result is fulfilled on the median of the values gathered each second.

dades <- loadData("../log14/log14.csv","BSC 100 / 20",100,20)
draw1(dades)

drawsmooth(dades)+scale_y_continuous(limits=c(0,250))
Ignoring unknown parameters: degree
pdf(file="BSC100_20_Timeline.pdf",width = 7, height= 5)
drawsmooth(dades)+scale_y_continuous(limits=c(0,250))
Ignoring unknown parameters: degree
dev.off()
png 
  2 

draw2(dades)

draw3(dades)

draw4(dades)
pdf(file="BSC100_20_ECDF.pdf",width = 7, height= 5)
draw4(dades)+scale_x_continuous(limits=c(0,250))
dev.off()
png 
  2 

Selected LOG33 URV 50 / 20

Shows that asking less BW (100 -> 50) allows to obtain the requested value for a tenant but does not allow to obtain it for the other one (asked 20 and obtained 10)

dades <- loadData("../log33/log33.csv","URV 50 / 20",50,20)
draw1(dades)

drawsmooth(dades)+scale_y_continuous(limits=c(0,100))
Ignoring unknown parameters: degree
pdf(file="URV50_20_Timeline.pdf",width = 7, height= 5)
drawsmooth(dades)+scale_y_continuous(limits=c(0,100))
Ignoring unknown parameters: degree
dev.off()
png 
  2 

draw2(dades)

draw3(dades)

draw4(dades)+scale_x_continuous(limits=c(0,120))
pdf(file="URV50_20_ECDF.pdf",width = 7, height= 5)
draw4(dades)+scale_x_continuous(limits=c(0,120))
dev.off()
png 
  2 

summaryBy(.~Tenant,URV10020,id = ~Timestamp,FUN = c(quantile))
dades <- loadData("../log27/log27.csv","BSC 50 / 20",20,50)
draw1(dades)

drawsmooth(dades)+scale_y_continuous(limits=c(0,100))
Ignoring unknown parameters: degree
pdf(file="BSC50_20_Timeline.pdf",width = 7, height= 5)
drawsmooth(dades)+scale_y_continuous(limits=c(0,100))
Ignoring unknown parameters: degree
dev.off()
png 
  2 

draw2(dades)

draw3(dades)

draw4(dades)+scale_x_continuous(limits=c(0,120))
pdf(file="BSC50_20_ECDF.pdf",width = 7, height= 5)
draw4(dades)+scale_x_continuous(limits=c(0,120))
dev.off()
png 
  2 

Experiment to show how exceeding the capabilities of the system works URV 100 / 100. Requests should go to different object stores so the results should be higher. But the median falls below the 40 MB/s

dades <- loadData("../log6/log6.csv","URV 100 / 100",100,100)
draw1(dades)

drawsmooth(dades)+scale_y_continuous(limits=c(0,100))
Ignoring unknown parameters: degree
pdf(file="URV100_100_Timeline.pdf",width = 7, height= 5)
drawsmooth(dades)+scale_y_continuous(limits=c(0,100))
Ignoring unknown parameters: degree
dev.off()
png 
  2 

draw2(dades)

draw3(dades)

draw4(dades)+scale_x_continuous(limits=c(0,120))
pdf(file="URV100_100_ECDF.pdf",width = 7, height= 5)
draw4(dades)+scale_x_continuous(limits=c(0,120))
dev.off()
png 
  2 

dades <- loadData("../log35/log35.csv","BSC 100 / 100",100,100)
draw1(dades)

drawsmooth(dades)+scale_y_continuous(limits=c(0,100))
Ignoring unknown parameters: degree
pdf(file="BSC100_100_Timeline.pdf",width = 7, height= 5)
drawsmooth(dades)+scale_y_continuous(limits=c(0,100))
Ignoring unknown parameters: degree
dev.off()
png 
  2 

draw2(dades)

draw3(dades)

draw4(dades)+scale_x_continuous(limits=c(0,120))
pdf(file="BSC100_100_ECDF.pdf",width = 7, height= 5)
draw4(dades)+scale_x_continuous(limits=c(0,120))
dev.off()
png 
  2 

Experiment to show how exceeding the capabilities of the system works URV 50 / 50 Requests should go to different object stores so the results should be higher. But the median falls below the 40 MB/s. The results are worse than the 100/100 scenario.

dades <- loadData("../log8/log8.csv","URV 50 / 50",50,50)
draw1(dades)

drawsmooth(dades)+scale_y_continuous(limits=c(0,250))
Ignoring unknown parameters: degree
pdf(file="URV50_50_Timeline.pdf",width = 7, height= 5)
drawsmooth(dades)+scale_y_continuous(limits=c(0,250))
Ignoring unknown parameters: degree
dev.off()
png 
  2 

draw2(dades)

draw3(dades)

draw4(dades)+scale_x_continuous(limits=c(0,250))
pdf(file="URV50_50_ECDF.pdf",width = 7, height= 5)
draw4(dades)+scale_x_continuous(limits=c(0,250))
dev.off()
png 
  2 

A less demanding bw differentation, for example 50 / 50 shows how we exceed the asked capabilities.

dades <- loadData("../log11/log11.csv","BSC 50 / 50",50,50)
draw1(dades)

drawsmooth(dades)+scale_y_continuous(limits=c(0,250))
Ignoring unknown parameters: degree
pdf(file="BSC50_50_Timeline.pdf",width = 7, height= 5)
drawsmooth(dades)+scale_y_continuous(limits=c(0,250))
Ignoring unknown parameters: degree
dev.off()
png 
  2 

draw2(dades)

draw3(dades)

draw4(dades)+scale_x_continuous(limits=c(0,250))
pdf(file="BSC50_50_ECDF.pdf",width = 7, height= 5)
draw4(dades)+scale_x_continuous(limits=c(0,250))
dev.off()
png 
  2 

dades <- loadData("../log38/log38.csv","URV 20 / 10",20,10)
draw1(dades)

drawsmooth(dades)+scale_y_continuous(limits=c(0,250))
Ignoring unknown parameters: degree
pdf(file="URV20_10_Timeline.pdf",width = 7, height= 5)
drawsmooth(dades)+scale_y_continuous(limits=c(0,250))
Ignoring unknown parameters: degree
dev.off()
png 
  2 

draw2(dades)

draw3(dades)

draw4(dades)+scale_x_continuous(limits=c(0,250))
pdf(file="URV20_10_ECDF.pdf",width = 7, height= 5)
draw4(dades)+scale_x_continuous(limits=c(0,250))
dev.off()
png 
  2 

dades <- loadData("../log40/log40.csv","BSC 20 / 10",20,10)
draw1(dades)

drawsmooth(dades)+scale_y_continuous(limits=c(0,250))
Ignoring unknown parameters: degree
pdf(file="BSC20_10_Timeline.pdf",width = 7, height= 5)
drawsmooth(dades)+scale_y_continuous(limits=c(0,250))
Ignoring unknown parameters: degree
dev.off()
png 
  2 

draw2(dades)

draw3(dades)

draw4(dades)+scale_x_continuous(limits=c(0,250))
pdf(file="BSC20_10_ECDF.pdf",width = 7, height= 5)
draw4(dades)+scale_x_continuous(limits=c(0,250))
dev.off()
png 
  2 

dades <- loadData("../log19/log19.csv","URV 50 / 20 / Outside interference of 10 MB/s ",50,20)
draw1(dades)

drawsmooth(dades)+scale_y_continuous(limits=c(0,200))
Ignoring unknown parameters: degree
pdf(file="URV50_20_10i_Timeline.pdf",width = 7, height= 5)
drawsmooth(dades)+scale_y_continuous(limits=c(0,200))
Ignoring unknown parameters: degree
dev.off()
png 
  2 

draw2(dades)

draw3(dades)

draw4(dades)+scale_x_continuous(limits=c(0,200))
pdf(file="URV50_20_10i_ECDF.pdf",width = 7, height= 5)
draw4(dades)+scale_x_continuous(limits=c(0,200))
dev.off()
png 
  2 

dades <- loadData("../log26/log26.csv","BSC 50 / 20 / Outside interference of 10 MB/s",20,50)
draw1(dades)

drawsmooth(dades)+scale_y_continuous(limits=c(0,200))
Ignoring unknown parameters: degree
pdf(file="BSC50_20_10i_Timeline.pdf",width = 7, height= 5)
drawsmooth(dades)+scale_y_continuous(limits=c(0,200))
Ignoring unknown parameters: degree
dev.off()
png 
  2 

draw2(dades)

draw3(dades)

draw4(dades)+scale_x_continuous(limits=c(0,200))
pdf(file="BSC50_20_10i_ECDF.pdf",width = 7, height= 5)
draw4(dades)+scale_x_continuous(limits=c(0,200))
dev.off()
png 
  2 

dades <- loadData("../log20/log20.csv","URV 50 / 50 / Outside interference of 10 MB/s ",50,50)
draw1(dades)

drawsmooth(dades)
Ignoring unknown parameters: degree

draw2(dades)

draw3(dades)

draw4(dades)

dades <- loadData("../log36/log36.csv","BSC 50 / 20 / Outside interference of 20 MB/s",50,20)
draw1(dades)

drawsmooth(dades)+scale_y_continuous(limits=c(0,150))
Ignoring unknown parameters: degree
pdf(file="BSC50_20_20i_Timeline.pdf",width = 7, height= 5)
drawsmooth(dades)+scale_y_continuous(limits=c(0,150))
Ignoring unknown parameters: degree
dev.off()
png 
  2 

draw2(dades)

draw3(dades)

draw4(dades)+scale_x_continuous(limits=c(0,150))
pdf(file="BSC50_20_20i_ECDF.pdf",width = 7, height= 5)
draw4(dades)+scale_x_continuous(limits=c(0,150))
dev.off()
png 
  2 

dades <- loadData("../log32/log32.csv","BSC 100 / 20 / Outside interference of 20 MB/s",20,100)
draw1(dades)

dades <- loadData("../log29/log29.csv","BSC 100 / 20 / Outside interference of 10 MB/s",20,100)
draw1(dades)

drawsmooth(dades)
Ignoring unknown parameters: degree

draw2(dades)

draw3(dades)

draw4(dades)

dades <- loadData("../log30/log30.csv","BSC 100 / 20 / Outside interference of 10 MB/s",20,100)
draw1(dades)

drawsmooth(dades)
Ignoring unknown parameters: degree

draw2(dades)

draw3(dades)

draw4(dades)

dades <- loadData("../log31/log31.csv","BSC 100 / 20 / Outside interference of 10 MB/s",20,100)
draw1(dades)

drawsmooth(dades)
Ignoring unknown parameters: degree

draw2(dades)

draw3(dades)

draw4(dades)

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OgogIHBkZl9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHJlc2hhcGUyKQpsaWJyYXJ5KGRvQnkpCmxvYWREYXRhIDwtIGZ1bmN0aW9uKEZJTEUsZGVzYyxsYWJlbDEsbGFiZWwyKQp7CmQgPC0gcmVhZC5jc3YoRklMRSxoZWFkZXIgPSBGQUxTRSkKaWYobGFiZWwyID4gbGFiZWwxKQp7CiAgdG1wIDwtIGxhYmVsMgogIGxhYmVsMiA8LSBsYWJlbDEKICBsYWJlbDEgPC0gdG1wCiAgdG1wIDwtIGRbMV0KICBkWzFdIDwtIGRbMl0KICBkWzJdIDwtIHRtcAp9CmQkVGltZVN0YW1wIDwtIDE6bnJvdyhkKQpuYW1lcyhkKSA8LSBjKHBhc3RlKCJUZW5hbnQgMSBAIixsYWJlbDEsIk1CL3MiKSwgcGFzdGUoIlRlbmFudCAyIEAiLGxhYmVsMiwiTUIvcyIpLCJUaW1lc3RhbXAiKQpkIDwtIG1lbHQoZCxpZC52YXJzPWMoIlRpbWVzdGFtcCIpKQpuYW1lcyhkKSA8LSBjKCJUaW1lc3RhbXAiLCJUZW5hbnQiLCJCVyIpCmQkZGVzYyA8LSBkZXNjCmQkbGFiZWwxIDwtIGxhYmVsMQpkJGxhYmVsMiA8LSBsYWJlbDIKcmV0dXJuIChkKQp9Cgpsb2FkRGF0YTEgPC0gZnVuY3Rpb24oRklMRSxkZXNjLGxhYmVsMSkKewpkIDwtIHJlYWQuY3N2KEZJTEUsaGVhZGVyID0gRkFMU0UpCmQkVGltZVN0YW1wIDwtIDE6bnJvdyhkKQpuYW1lcyhkKSA8LSBjKCJUZW5hbnQgMSIsICJUaW1lc3RhbXAiKQpkIDwtIG1lbHQoZCxpZC52YXJzPWMoIlRpbWVzdGFtcCIpKQpuYW1lcyhkKSA8LSBjKCJUaW1lc3RhbXAiLCJUZW5hbnQiLCJCVyIpCmQkZGVzYyA8LSBkZXNjCnJldHVybiAoZCkKfQoKZHJhdzEgPC0gZnVuY3Rpb24oZGFkZXMpCnsKICBnZ3Bsb3QoZGFkZXMpK2dlb21fbGluZShhZXMoeD1UaW1lc3RhbXAseT1CVyxjb2xvdXI9VGVuYW50LGxpbmV0eXBlPVRlbmFudCkpK3RoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0KStsYWJzKHRpdGxlPShkYWRlcyRkZXNjKSkrdGhlbWUoIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQp9CmRyYXdzbW9vdGggPC0gZnVuY3Rpb24oZGFkZXMpCnsKICBnZ3Bsb3QoZGFkZXMpK2dlb21fc21vb3RoKGFlcyh4PVRpbWVzdGFtcCx5PUJXLGNvbG91cj1UZW5hbnQsbGluZXR5cGU9VGVuYW50KSwgZGVncmVlPTAsIAogICAgICAgIHNwYW49MC4wNSwgc2U9RkFMU0UpK3RoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0KStsYWJzKHRpdGxlPShkYWRlcyRkZXNjKSkrdGhlbWUoIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQp9CmRyYXcyIDwtIGZ1bmN0aW9uKGRhZGVzKQp7CiAgZ2dwbG90KGRhZGVzKStnZW9tX2JveHBsb3QoYWVzKHg9VGVuYW50LHk9QlcpKSt0aGVtZV9idygpK2xhYnModGl0bGU9KGRhZGVzJGRlc2MpKQp9CmRyYXczIDwtIGZ1bmN0aW9uKGRhZGVzKQp7CiAgZ2dwbG90KGRhZGVzKStnZW9tX3Zpb2xpbihhZXMoeD1UZW5hbnQseT1CVyksZHJhd19xdWFudGlsZXMgPSBjKDAuNSkpK3RoZW1lX2J3KCkrbGFicyh0aXRsZT0oZGFkZXMkZGVzYykpCn0KCmRyYXc0IDwtIGZ1bmN0aW9uKGRhZGVzKQp7CiAgZ2dwbG90KGRhZGVzLGFlcyhjb2xvdXI9VGVuYW50LHg9QlcsbGluZXR5cGU9VGVuYW50KSkrIHN0YXRfZWNkZihnZW9tID0gInN0ZXAiKStnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9ZGFkZXMkbGFiZWwxLGNvbG91cj0iYmxhY2siKStnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9ZGFkZXMkbGFiZWwyLGNvbG91cj0iYmxhY2siKSt0aGVtZV9idyhiYXNlX3NpemUgPSAxNCkrbGFicyh0aXRsZT0oZGFkZXMkZGVzYykpK3NjYWxlX3lfY29udGludW91cygiZWNkZiIpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQp9CiAKCmBgYAoKIyBTZWxlY3RlZCBMT0cxLkNTViBVUlYgMTAwIC8gMjAKU2hvd3MgaG93IHRoZSBtZWNoYW5pc20gZ3VhcmFudGVlIHRoZSAyMCBNQi9zIGJ1dCBkb2VzIG5vdCBndWFyYW50ZWUgdGhlIDEwMCBNQi9zCiMjIExpbmUgcGxvdCArIFZpb2xpbiBwbG90CgoKYGBge3J9ClVSVjEwMDIwIDwtIGxvYWREYXRhKCIuLi9sb2cxL2xvZzEuY3N2IiwiVVJWIDEwMCAvIDIwIiwgMTAwLCAyMCkKZHJhdzEoVVJWMTAwMjApCgpkcmF3c21vb3RoKFVSVjEwMDIwKStzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoMCwyNTApKQpwZGYoZmlsZT0iVVJWMTAwXzIwX1RpbWVsaW5lLnBkZiIsd2lkdGggPSA3LCBoZWlnaHQ9IDUpCmRyYXdzbW9vdGgoVVJWMTAwMjApK3NjYWxlX3lfY29udGludW91cyhsaW1pdHM9YygwLDI1MCkpCmRldi5vZmYoKQpkcmF3MihVUlYxMDAyMCkKZHJhdzMoVVJWMTAwMjApCmRyYXc0KFVSVjEwMDIwKStzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwyNTApKQpwZGYoZmlsZT0iVVJWMTAwXzIwX0VDREYucGRmIix3aWR0aCA9IDcsIGhlaWdodD0gNSkKZHJhdzQoVVJWMTAwMjApK3NjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygwLDI1MCkpCmRldi5vZmYoKQpzdW1tYXJ5QnkoLn5UZW5hbnQsVVJWMTAwMjAsaWQgPSB+VGltZXN0YW1wLEZVTiA9IGMocXVhbnRpbGUpKQpgYGAKIyBCU0MgZmlsdGVyIGFsbG93cyB0byByZXF1ZXN0IGEgMTAwIC8gMjAgQlcgYW5kIHRoZSByZXN1bHQgaXMgZnVsZmlsbGVkIG9uIHRoZSBtZWRpYW4gb2YgdGhlIHZhbHVlcyBnYXRoZXJlZCBlYWNoIHNlY29uZC4KCmBgYHtyfQpkYWRlcyA8LSBsb2FkRGF0YSgiLi4vbG9nMTQvbG9nMTQuY3N2IiwiQlNDIDEwMCAvIDIwIiwxMDAsMjApCmRyYXcxKGRhZGVzKQpkcmF3c21vb3RoKGRhZGVzKStzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoMCwyNTApKQpwZGYoZmlsZT0iQlNDMTAwXzIwX1RpbWVsaW5lLnBkZiIsd2lkdGggPSA3LCBoZWlnaHQ9IDUpCmRyYXdzbW9vdGgoZGFkZXMpK3NjYWxlX3lfY29udGludW91cyhsaW1pdHM9YygwLDI1MCkpCmRldi5vZmYoKQpkcmF3MihkYWRlcykKZHJhdzMoZGFkZXMpCmRyYXc0KGRhZGVzKQpwZGYoZmlsZT0iQlNDMTAwXzIwX0VDREYucGRmIix3aWR0aCA9IDcsIGhlaWdodD0gNSkKZHJhdzQoZGFkZXMpK3NjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygwLDI1MCkpCmRldi5vZmYoKQpgYGAKCgojIFNlbGVjdGVkIExPRzMzIFVSViA1MCAvIDIwIApTaG93cyB0aGF0IGFza2luZyBsZXNzIEJXICgxMDAgLT4gNTApIGFsbG93cyB0byBvYnRhaW4gdGhlIHJlcXVlc3RlZCB2YWx1ZSBmb3IgYSB0ZW5hbnQgYnV0IGRvZXMgbm90IGFsbG93IHRvIG9idGFpbiBpdCBmb3IgdGhlIG90aGVyIG9uZSAoYXNrZWQgMjAgYW5kIG9idGFpbmVkIDEwKQoKYGBge3J9CmRhZGVzIDwtIGxvYWREYXRhKCIuLi9sb2czMy9sb2czMy5jc3YiLCJVUlYgNTAgLyAyMCIsNTAsMjApCmRyYXcxKGRhZGVzKQpkcmF3c21vb3RoKGRhZGVzKStzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoMCwxMDApKQpwZGYoZmlsZT0iVVJWNTBfMjBfVGltZWxpbmUucGRmIix3aWR0aCA9IDcsIGhlaWdodD0gNSkKZHJhd3Ntb290aChkYWRlcykrc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsMTAwKSkKZGV2Lm9mZigpCmRyYXcyKGRhZGVzKQpkcmF3MyhkYWRlcykKZHJhdzQoZGFkZXMpK3NjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygwLDEyMCkpCnBkZihmaWxlPSJVUlY1MF8yMF9FQ0RGLnBkZiIsd2lkdGggPSA3LCBoZWlnaHQ9IDUpCmRyYXc0KGRhZGVzKStzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwxMjApKQpkZXYub2ZmKCkKc3VtbWFyeUJ5KC5+VGVuYW50LFVSVjEwMDIwLGlkID0gflRpbWVzdGFtcCxGVU4gPSBjKHF1YW50aWxlKSkKYGBgCmBgYHtyfQpkYWRlcyA8LSBsb2FkRGF0YSgiLi4vbG9nMjcvbG9nMjcuY3N2IiwiQlNDIDUwIC8gMjAiLDIwLDUwKQpkcmF3MShkYWRlcykKZHJhd3Ntb290aChkYWRlcykrc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsMTAwKSkKcGRmKGZpbGU9IkJTQzUwXzIwX1RpbWVsaW5lLnBkZiIsd2lkdGggPSA3LCBoZWlnaHQ9IDUpCmRyYXdzbW9vdGgoZGFkZXMpK3NjYWxlX3lfY29udGludW91cyhsaW1pdHM9YygwLDEwMCkpCmRldi5vZmYoKQpkcmF3MihkYWRlcykKZHJhdzMoZGFkZXMpCmRyYXc0KGRhZGVzKStzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwxMjApKQpwZGYoZmlsZT0iQlNDNTBfMjBfRUNERi5wZGYiLHdpZHRoID0gNywgaGVpZ2h0PSA1KQpkcmF3NChkYWRlcykrc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDAsMTIwKSkKZGV2Lm9mZigpCmBgYAoKCgojIEV4cGVyaW1lbnQgdG8gc2hvdyBob3cgZXhjZWVkaW5nIHRoZSBjYXBhYmlsaXRpZXMgb2YgdGhlIHN5c3RlbSB3b3JrcyBVUlYgMTAwIC8gMTAwLiBSZXF1ZXN0cyBzaG91bGQgZ28gdG8gZGlmZmVyZW50IG9iamVjdCBzdG9yZXMgc28gdGhlIHJlc3VsdHMgc2hvdWxkIGJlIGhpZ2hlci4gQnV0IHRoZSBtZWRpYW4gZmFsbHMgYmVsb3cgdGhlIDQwIE1CL3MKYGBge3J9CmRhZGVzIDwtIGxvYWREYXRhKCIuLi9sb2c2L2xvZzYuY3N2IiwiVVJWIDEwMCAvIDEwMCIsMTAwLDEwMCkKZHJhdzEoZGFkZXMpCmRyYXdzbW9vdGgoZGFkZXMpK3NjYWxlX3lfY29udGludW91cyhsaW1pdHM9YygwLDEwMCkpCnBkZihmaWxlPSJVUlYxMDBfMTAwX1RpbWVsaW5lLnBkZiIsd2lkdGggPSA3LCBoZWlnaHQ9IDUpCmRyYXdzbW9vdGgoZGFkZXMpK3NjYWxlX3lfY29udGludW91cyhsaW1pdHM9YygwLDEwMCkpCmRldi5vZmYoKQpkcmF3MihkYWRlcykKZHJhdzMoZGFkZXMpCmRyYXc0KGRhZGVzKStzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwxMjApKQpwZGYoZmlsZT0iVVJWMTAwXzEwMF9FQ0RGLnBkZiIsd2lkdGggPSA3LCBoZWlnaHQ9IDUpCmRyYXc0KGRhZGVzKStzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwxMjApKQpkZXYub2ZmKCkKYGBgCmBgYHtyfQpkYWRlcyA8LSBsb2FkRGF0YSgiLi4vbG9nMzUvbG9nMzUuY3N2IiwiQlNDIDEwMCAvIDEwMCIsMTAwLDEwMCkKZHJhdzEoZGFkZXMpCmRyYXdzbW9vdGgoZGFkZXMpK3NjYWxlX3lfY29udGludW91cyhsaW1pdHM9YygwLDEwMCkpCnBkZihmaWxlPSJCU0MxMDBfMTAwX1RpbWVsaW5lLnBkZiIsd2lkdGggPSA3LCBoZWlnaHQ9IDUpCmRyYXdzbW9vdGgoZGFkZXMpK3NjYWxlX3lfY29udGludW91cyhsaW1pdHM9YygwLDEwMCkpCmRldi5vZmYoKQpkcmF3MihkYWRlcykKZHJhdzMoZGFkZXMpCmRyYXc0KGRhZGVzKStzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwxMjApKQpwZGYoZmlsZT0iQlNDMTAwXzEwMF9FQ0RGLnBkZiIsd2lkdGggPSA3LCBoZWlnaHQ9IDUpCmRyYXc0KGRhZGVzKStzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwxMjApKQpkZXYub2ZmKCkKYGBgCiMgRXhwZXJpbWVudCB0byBzaG93IGhvdyBleGNlZWRpbmcgdGhlIGNhcGFiaWxpdGllcyBvZiB0aGUgc3lzdGVtIHdvcmtzIFVSViA1MCAvIDUwIFJlcXVlc3RzIHNob3VsZCBnbyB0byBkaWZmZXJlbnQgb2JqZWN0IHN0b3JlcyBzbyB0aGUgcmVzdWx0cyBzaG91bGQgYmUgaGlnaGVyLiBCdXQgdGhlIG1lZGlhbiBmYWxscyBiZWxvdyB0aGUgNDAgTUIvcy4gVGhlIHJlc3VsdHMgYXJlIHdvcnNlIHRoYW4gdGhlIDEwMC8xMDAgc2NlbmFyaW8uCgpgYGB7cn0KZGFkZXMgPC0gbG9hZERhdGEoIi4uL2xvZzgvbG9nOC5jc3YiLCJVUlYgNTAgLyA1MCIsNTAsNTApCmRyYXcxKGRhZGVzKQpkcmF3c21vb3RoKGRhZGVzKStzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoMCwyNTApKQpwZGYoZmlsZT0iVVJWNTBfNTBfVGltZWxpbmUucGRmIix3aWR0aCA9IDcsIGhlaWdodD0gNSkKZHJhd3Ntb290aChkYWRlcykrc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsMjUwKSkKZGV2Lm9mZigpCmRyYXcyKGRhZGVzKQpkcmF3MyhkYWRlcykKZHJhdzQoZGFkZXMpK3NjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygwLDI1MCkpCnBkZihmaWxlPSJVUlY1MF81MF9FQ0RGLnBkZiIsd2lkdGggPSA3LCBoZWlnaHQ9IDUpCmRyYXc0KGRhZGVzKStzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwyNTApKQpkZXYub2ZmKCkKYGBgCgoKIyBBIGxlc3MgZGVtYW5kaW5nIGJ3IGRpZmZlcmVudGF0aW9uLCBmb3IgZXhhbXBsZSA1MCAvIDUwIHNob3dzIGhvdyB3ZSBleGNlZWQgdGhlIGFza2VkIGNhcGFiaWxpdGllcy4gCmBgYHtyfQpkYWRlcyA8LSBsb2FkRGF0YSgiLi4vbG9nMTEvbG9nMTEuY3N2IiwiQlNDIDUwIC8gNTAiLDUwLDUwKQpkcmF3MShkYWRlcykKZHJhd3Ntb290aChkYWRlcykrc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsMjUwKSkKcGRmKGZpbGU9IkJTQzUwXzUwX1RpbWVsaW5lLnBkZiIsd2lkdGggPSA3LCBoZWlnaHQ9IDUpCmRyYXdzbW9vdGgoZGFkZXMpK3NjYWxlX3lfY29udGludW91cyhsaW1pdHM9YygwLDI1MCkpCmRldi5vZmYoKQpkcmF3MihkYWRlcykKZHJhdzMoZGFkZXMpCmRyYXc0KGRhZGVzKStzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwyNTApKQpwZGYoZmlsZT0iQlNDNTBfNTBfRUNERi5wZGYiLHdpZHRoID0gNywgaGVpZ2h0PSA1KQpkcmF3NChkYWRlcykrc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDAsMjUwKSkKZGV2Lm9mZigpCmBgYAoKYGBge3J9CmRhZGVzIDwtIGxvYWREYXRhKCIuLi9sb2czOC9sb2czOC5jc3YiLCJVUlYgMjAgLyAxMCIsMjAsMTApCmRyYXcxKGRhZGVzKQpkcmF3c21vb3RoKGRhZGVzKStzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoMCwyNTApKQpwZGYoZmlsZT0iVVJWMjBfMTBfVGltZWxpbmUucGRmIix3aWR0aCA9IDcsIGhlaWdodD0gNSkKZHJhd3Ntb290aChkYWRlcykrc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsMjUwKSkKZGV2Lm9mZigpCmRyYXcyKGRhZGVzKQpkcmF3MyhkYWRlcykKZHJhdzQoZGFkZXMpK3NjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygwLDI1MCkpCnBkZihmaWxlPSJVUlYyMF8xMF9FQ0RGLnBkZiIsd2lkdGggPSA3LCBoZWlnaHQ9IDUpCmRyYXc0KGRhZGVzKStzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwyNTApKQpkZXYub2ZmKCkKYGBgCgpgYGB7cn0KZGFkZXMgPC0gbG9hZERhdGEoIi4uL2xvZzQwL2xvZzQwLmNzdiIsIkJTQyAyMCAvIDEwIiwyMCwxMCkKZHJhdzEoZGFkZXMpCmRyYXdzbW9vdGgoZGFkZXMpK3NjYWxlX3lfY29udGludW91cyhsaW1pdHM9YygwLDI1MCkpCnBkZihmaWxlPSJCU0MyMF8xMF9UaW1lbGluZS5wZGYiLHdpZHRoID0gNywgaGVpZ2h0PSA1KQpkcmF3c21vb3RoKGRhZGVzKStzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoMCwyNTApKQpkZXYub2ZmKCkKZHJhdzIoZGFkZXMpCmRyYXczKGRhZGVzKQpkcmF3NChkYWRlcykrc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDAsMjUwKSkKcGRmKGZpbGU9IkJTQzIwXzEwX0VDREYucGRmIix3aWR0aCA9IDcsIGhlaWdodD0gNSkKZHJhdzQoZGFkZXMpK3NjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygwLDI1MCkpCmRldi5vZmYoKQpgYGAKCgpgYGB7cn0KZGFkZXMgPC0gbG9hZERhdGEoIi4uL2xvZzE5L2xvZzE5LmNzdiIsIlVSViA1MCAvIDIwIC8gT3V0c2lkZSBpbnRlcmZlcmVuY2Ugb2YgMTAgTUIvcyAiLDUwLDIwKQpkcmF3MShkYWRlcykKZHJhd3Ntb290aChkYWRlcykrc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsMjAwKSkKcGRmKGZpbGU9IlVSVjUwXzIwXzEwaV9UaW1lbGluZS5wZGYiLHdpZHRoID0gNywgaGVpZ2h0PSA1KQpkcmF3c21vb3RoKGRhZGVzKStzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoMCwyMDApKQpkZXYub2ZmKCkKZHJhdzIoZGFkZXMpCmRyYXczKGRhZGVzKQpkcmF3NChkYWRlcykrc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDAsMjAwKSkKcGRmKGZpbGU9IlVSVjUwXzIwXzEwaV9FQ0RGLnBkZiIsd2lkdGggPSA3LCBoZWlnaHQ9IDUpCmRyYXc0KGRhZGVzKStzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwyMDApKQpkZXYub2ZmKCkKYGBgCmBgYHtyfQpkYWRlcyA8LSBsb2FkRGF0YSgiLi4vbG9nMjYvbG9nMjYuY3N2IiwiQlNDIDUwIC8gMjAgLyBPdXRzaWRlIGludGVyZmVyZW5jZSBvZiAxMCBNQi9zIiwyMCw1MCkKZHJhdzEoZGFkZXMpCmRyYXdzbW9vdGgoZGFkZXMpK3NjYWxlX3lfY29udGludW91cyhsaW1pdHM9YygwLDIwMCkpCnBkZihmaWxlPSJCU0M1MF8yMF8xMGlfVGltZWxpbmUucGRmIix3aWR0aCA9IDcsIGhlaWdodD0gNSkKZHJhd3Ntb290aChkYWRlcykrc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsMjAwKSkKZGV2Lm9mZigpCmRyYXcyKGRhZGVzKQpkcmF3MyhkYWRlcykKZHJhdzQoZGFkZXMpK3NjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygwLDIwMCkpCnBkZihmaWxlPSJCU0M1MF8yMF8xMGlfRUNERi5wZGYiLHdpZHRoID0gNywgaGVpZ2h0PSA1KQpkcmF3NChkYWRlcykrc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDAsMjAwKSkKZGV2Lm9mZigpCmBgYAoKCmBgYHtyfQpkYWRlcyA8LSBsb2FkRGF0YSgiLi4vbG9nMjAvbG9nMjAuY3N2IiwiVVJWIDUwIC8gNTAgLyBPdXRzaWRlIGludGVyZmVyZW5jZSBvZiAxMCBNQi9zICIsNTAsNTApCmRyYXcxKGRhZGVzKQpkcmF3c21vb3RoKGRhZGVzKQpkcmF3MihkYWRlcykKZHJhdzMoZGFkZXMpCmRyYXc0KGRhZGVzKQpgYGAKCmBgYHtyfQpkYWRlcyA8LSBsb2FkRGF0YSgiLi4vbG9nMjEvbG9nMjEuY3N2IiwiVVJWIDUwIC8gMjAgLyBPdXRzaWRlIGludGVyZmVyZW5jZSBvZiAyMCBNQi9zICIsNTAsMjApCmRyYXcxKGRhZGVzKQpkcmF3c21vb3RoKGRhZGVzKStzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoMCwxNTApKQpwZGYoZmlsZT0iVVJWNTBfMjBfMjBpX1RpbWVsaW5lLnBkZiIsd2lkdGggPSA3LCBoZWlnaHQ9IDUpCmRyYXdzbW9vdGgoZGFkZXMpK3NjYWxlX3lfY29udGludW91cyhsaW1pdHM9YygwLDE1MCkpCmRldi5vZmYoKQpkcmF3MihkYWRlcykKZHJhdzMoZGFkZXMpCmRyYXc0KGRhZGVzKStzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwxNTApKQpwZGYoZmlsZT0iVVJWNTBfMjBfMjBpX0VDREYucGRmIix3aWR0aCA9IDcsIGhlaWdodD0gNSkKZHJhdzQoZGFkZXMpK3NjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygwLDE1MCkpCmRldi5vZmYoKQpgYGAKCmBgYHtyfQpkYWRlcyA8LSBsb2FkRGF0YSgiLi4vbG9nMzYvbG9nMzYuY3N2IiwiQlNDIDUwIC8gMjAgLyBPdXRzaWRlIGludGVyZmVyZW5jZSBvZiAyMCBNQi9zIiw1MCwyMCkKZHJhdzEoZGFkZXMpCmRyYXdzbW9vdGgoZGFkZXMpK3NjYWxlX3lfY29udGludW91cyhsaW1pdHM9YygwLDE1MCkpCnBkZihmaWxlPSJCU0M1MF8yMF8yMGlfVGltZWxpbmUucGRmIix3aWR0aCA9IDcsIGhlaWdodD0gNSkKZHJhd3Ntb290aChkYWRlcykrc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKDAsMTUwKSkKZGV2Lm9mZigpCmRyYXcyKGRhZGVzKQpkcmF3MyhkYWRlcykKZHJhdzQoZGFkZXMpK3NjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygwLDE1MCkpCnBkZihmaWxlPSJCU0M1MF8yMF8yMGlfRUNERi5wZGYiLHdpZHRoID0gNywgaGVpZ2h0PSA1KQpkcmF3NChkYWRlcykrc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDAsMTUwKSkKZGV2Lm9mZigpCmBgYAoKCmBgYHtyfQpkYWRlcyA8LSBsb2FkRGF0YSgiLi4vbG9nMzIvbG9nMzIuY3N2IiwiQlNDIDEwMCAvIDIwIC8gT3V0c2lkZSBpbnRlcmZlcmVuY2Ugb2YgMjAgTUIvcyIsMjAsMTAwKQpkcmF3MShkYWRlcykKZHJhd3Ntb290aChkYWRlcykKZHJhdzIoZGFkZXMpCmRyYXczKGRhZGVzKQpkcmF3NChkYWRlcykKYGBgCgoKCmBgYHtyfQpkYWRlcyA8LSBsb2FkRGF0YSgiLi4vbG9nMjkvbG9nMjkuY3N2IiwiQlNDIDEwMCAvIDIwIC8gT3V0c2lkZSBpbnRlcmZlcmVuY2Ugb2YgMTAgTUIvcyIsMjAsMTAwKQpkcmF3MShkYWRlcykKZHJhd3Ntb290aChkYWRlcykKZHJhdzIoZGFkZXMpCmRyYXczKGRhZGVzKQpkcmF3NChkYWRlcykKYGBgCgpgYGB7cn0KZGFkZXMgPC0gbG9hZERhdGEoIi4uL2xvZzMwL2xvZzMwLmNzdiIsIkJTQyAxMDAgLyAyMCAvIE91dHNpZGUgaW50ZXJmZXJlbmNlIG9mIDEwIE1CL3MiLDIwLDEwMCkKZHJhdzEoZGFkZXMpCmRyYXdzbW9vdGgoZGFkZXMpCmRyYXcyKGRhZGVzKQpkcmF3MyhkYWRlcykKZHJhdzQoZGFkZXMpCmBgYAoKCmBgYHtyfQpkYWRlcyA8LSBsb2FkRGF0YSgiLi4vbG9nMzEvbG9nMzEuY3N2IiwiQlNDIDEwMCAvIDIwIC8gT3V0c2lkZSBpbnRlcmZlcmVuY2Ugb2YgMTAgTUIvcyIsMjAsMTAwKQpkcmF3MShkYWRlcykKZHJhd3Ntb290aChkYWRlcykKZHJhdzIoZGFkZXMpCmRyYXczKGRhZGVzKQpkcmF3NChkYWRlcykKYGBgCgoKCgoK